aboutsummaryrefslogtreecommitdiffstats
path: root/src/app/groups/[groupId]/expenses/expense-list.tsx
blob: 9217123603c6f7c08809d86f6bdc59cd6d3ed574 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
'use client'
import { CategoryIcon } from '@/app/groups/[groupId]/expenses/category-icon'
import { Button } from '@/components/ui/button'
import { getGroupExpenses } from '@/lib/api'
import { cn } from '@/lib/utils'
import { Participant } from '@prisma/client'
import { ChevronRight } from 'lucide-react'
import Link from 'next/link'
import { useRouter } from 'next/navigation'
import { Fragment, useEffect } from 'react'

type Props = {
  expenses: Awaited<ReturnType<typeof getGroupExpenses>>
  participants: Participant[]
  currency: string
  groupId: string
}

export function ExpenseList({
  expenses,
  currency,
  participants,
  groupId,
}: Props) {
  useEffect(() => {
    const activeUser = localStorage.getItem('newGroup-activeUser')
    const newUser = localStorage.getItem(`${groupId}-newUser`)
    if (activeUser || newUser) {
      localStorage.removeItem('newGroup-activeUser')
      localStorage.removeItem(`${groupId}-newUser`)
      if (activeUser === 'None') {
        localStorage.setItem(`${groupId}-activeUser`, 'None')
      } else {
        const userId = participants.find(
          (p) => p.name === (activeUser || newUser),
        )?.id
        if (userId) {
          localStorage.setItem(`${groupId}-activeUser`, userId)
        }
      }
    }
  }, [groupId, participants])

  const getParticipant = (id: string) => participants.find((p) => p.id === id)
  const router = useRouter()

  return expenses.length > 0 ? (
    expenses.map((expense) => (
      <div
        key={expense.id}
        className={cn(
          'border-t flex justify-between px-4 sm:pr-2 sm:pl-6 py-4 text-sm cursor-pointer hover:bg-accent gap-1 items-stretch',
          expense.isReimbursement && 'italic',
        )}
        onClick={() => {
          router.push(`/groups/${groupId}/expenses/${expense.id}/edit`)
        }}
      >
        <CategoryIcon
          category={expense.category}
          className="w-4 h-4 mr-2 mt-0.5 text-muted-foreground"
        />
        <div className="flex-1">
          <div className={cn('mb-1', expense.isReimbursement && 'italic')}>
            {expense.title}
          </div>
          <div className="text-xs text-muted-foreground">
            Paid by <strong>{getParticipant(expense.paidById)?.name}</strong>{' '}
            for{' '}
            {expense.paidFor.map((paidFor, index) => (
              <Fragment key={index}>
                {index !== 0 && <>, </>}
                <strong>
                  {
                    participants.find((p) => p.id === paidFor.participantId)
                      ?.name
                  }
                </strong>
              </Fragment>
            ))}
          </div>
        </div>
        <div className="flex flex-col justify-between items-end">
          <div
            className={cn(
              'tabular-nums whitespace-nowrap',
              expense.isReimbursement ? 'italic' : 'font-bold',
            )}
          >
            {currency} {(expense.amount / 100).toFixed(2)}
          </div>
          <div className="text-xs text-muted-foreground">
            {formatDate(expense.expenseDate)}
          </div>
        </div>
        <Button
          size="icon"
          variant="link"
          className="self-center hidden sm:flex"
          asChild
        >
          <Link href={`/groups/${groupId}/expenses/${expense.id}/edit`}>
            <ChevronRight className="w-4 h-4" />
          </Link>
        </Button>
      </div>
    ))
  ) : (
    <p className="px-6 text-sm py-6">
      Your group doesn’t contain any expense yet.{' '}
      <Button variant="link" asChild className="-m-4">
        <Link href={`/groups/${groupId}/expenses/create`}>
          Create the first one
        </Link>
      </Button>
    </p>
  )
}

function formatDate(date: Date) {
  return date.toLocaleDateString('en-US', {
    dateStyle: 'medium',
    timeZone: 'UTC',
  })
}